/* Copyright (c) 2011 by Mani Brundha Kattamuri, Haritha Subramanyam
 *
 * Project Info:  http://code.google.com/p/andriod-travelapp-csc780/wiki/Design
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
 * USA.
 */

package com.example.TravelApp.search.advanced;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

import com.example.TravelApp.R;
import com.example.TravelApp.constants.MapConstants;

import com.example.TravelApp.search.common.PlaceObject;
import com.example.TravelApp.search.common.PlotItemizedOverlay;
import com.example.TravelApp.search.common.helper.MapDrawPathHelper;
import com.example.TravelApp.search.common.helper.PlacesDirectionHelper;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.google.android.maps.MapView;

import android.util.Log;
import android.widget.TextView;

/**
 * This activity is called when the user selects a venue address The layout is
 * described in file <code>res/layout/display_route.xml</code>. This activity
 * displays the route from the current location to the venue location on a map;
 * it uses Google Maps API for the route and location co-ordinates. GPS provider
 * is used to get current location details and an overlay is used to point the
 * current location. The location manager sends updates and the pointer is
 * updated accordingly
 * 
 * @author Mani Brundha and Haritha Subramanyam
 * 
 */
public class MapSrcToDestRouteActivity extends
		com.google.android.maps.MapActivity implements LocationListener,
		MapConstants {

	private LocationManager locationManager;
	private int position;
	private Drawable drawable;
	private PlotItemizedOverlay locationOverlays;
	private MapView mapView;
	private GeoPoint srcGeoPoint;
	private GeoPoint destGeoPoint;
	private List<Overlay> mapOverlays;
	private String place;

	private ArrayList<PlaceObject> list;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.display_route);
		// retrieve the values passed through the intent - list and the position
		// information
		Intent myIntent = getIntent();
		this.list = myIntent.getParcelableArrayListExtra("placesList");
		this.position = myIntent.getIntExtra("position", -1);
		place = (String) myIntent.getCharSequenceExtra("Place");
		// populate the text views with relevant information

		mapView = (MapView) findViewById(R.id.mapview);
		mapView.setBuiltInZoomControls(true);

		String title = "", rating = "";

		// First check for Null Pointers; proceeds only if the start
		// co-ordinates are available
		if ((position != 0 && MapDrawPathHelper.isNotNull(list
				.get(position - 1).getLatitudeAndLongitude()) == true)
				|| position == 0) {
			// Extract the start location lat and long from the list
			if (position != 0) {
				srcGeoPoint = MapDrawPathHelper.getGeoPoint(list.get(
						position - 1).getLatitudeAndLongitude());
				title = list.get(position - 1).getVenueName() + "\n\n"
						+ list.get(position - 1).getAddress();
				rating = list.get(position - 1).getRating();
			} else {
				// Since working on Emulator, last known location cannot be
				// known unless working on debug mode
				srcGeoPoint = MapDrawPathHelper.getGeoPoint(place);// get the
																	// current
																	// location
																	// of user
																	// from
																	// intent
				rating = "0";
				title = "Start";
			}

			// Extract Destination geo points from the list - the current venue
			// address

			// First check for Null Pointers; proceeds only if the dest
			// co-ordinates are available
			if (MapDrawPathHelper.isNotNull(list.get(position)
					.getLatitudeAndLongitude()) == true) {
				// construct a geopint out of the string
				destGeoPoint = MapDrawPathHelper.getGeoPoint(list.get(position)
						.getLatitudeAndLongitude());
				initFields(LOCATION_FROM_TAG, list.get(position).getAddress());
				// Draw route between the current and destination location using
				// route provided by Google Maps
				MapDrawPathHelper.drawPath(srcGeoPoint, destGeoPoint,
						Color.DKGRAY, mapView);
				// plot overlay for the start and dest locations on the route
				setOverlays(title, rating);
				// init the location manager and ask for updates
			} else {
				setContentView(R.layout.no_results_maps);// Displays No
															// co-ordinates
			}
			setLocationManager();
		} else {
			setContentView(R.layout.no_results_maps);// Displays No co-ordinates
		}
	}

	/**
	 * Places overlays on all the locations of places of interest in the list
	 * This method is called after the path is drawn between two points
	 * 
	 * @param index
	 *            - index of the item in the list of places sent through intent
	 * @param src
	 *            - From location GeoPoint
	 * @param dest
	 *            - To location GeoPoint
	 */
	private void setOverlays(String title, String rating) {
		mapOverlays = mapView.getOverlays();
		drawable = this.getResources().getDrawable(R.drawable.map_pin_green);
		locationOverlays = new PlotItemizedOverlay(drawable, this);

		OverlayItem overlayitemFinal = new OverlayItem(srcGeoPoint, title,
				rating);
		locationOverlays.addOverlay(overlayitemFinal);
		mapOverlays.add(locationOverlays);

		OverlayItem overlayitemd = new OverlayItem(destGeoPoint, list.get(
				position).getVenueName()
				+ "\n\n" + list.get(position).getAddress(), list.get(position)
				.getRating());
		locationOverlays.addOverlay(overlayitemd);
		mapOverlays.add(locationOverlays);

		mapView.getController().animateTo(srcGeoPoint);

		mapView.getController().setZoom(15);

	}

	/**
	 * Activates the Location Service in order to retrieve the current location
	 * information. The last known location is used as the source location in
	 * case no location change occurs
	 */
	private void setLocationManager() {

		locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		Criteria criteria = new Criteria();
		criteria.setAccuracy(Criteria.ACCURACY_FINE);
		criteria.setAltitudeRequired(false);
		Location lastKnownLocation = locationManager
				.getLastKnownLocation(locationManager.getBestProvider(criteria,
						true));
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
				1000, 5000, this);
	}

	/**
	 * Populates the text views on the Map route screen The text for those
	 * fields including the labels is set here
	 * 
	 * @param fromText
	 *            - Name/address of source location
	 * @param toText
	 *            - Address of destination location
	 */
	private void initFields(String fromText, String toText) {
		TextView fromLocationLbl = (TextView) findViewById(R.id.fromLocationLbl);
		TextView toLocationLbl = (TextView) findViewById(R.id.toLocationLbl);

		fromLocationLbl.setText("From :");
		toLocationLbl.setText("To : ");

		TextView fromLocationText = (TextView) findViewById(R.id.fromLocationText);
		TextView toLocationText = (TextView) findViewById(R.id.toLocationText);

		fromLocationText.setText(fromText);
		toLocationText.setText(toText);
	}

	// @Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	/**
	 * When the activity pauses all the location updates are removed before
	 * calling super.onPause
	 */
	@Override
	protected void onPause() {
		try {

			// remove the listener
			locationManager.removeUpdates(this);
		} catch (NullPointerException e) {
			Log.e("log_tag", "Error in recieving response" + e.toString());
		}

		super.onPause();
	}

	/**
	 * Requests for location updates whenever the activity resumes
	 */
	@Override
	protected void onResume() {
		// add the listener again
		try {

			locationManager.requestLocationUpdates(
					LocationManager.GPS_PROVIDER, 300000, 5000, this);
		} catch (NullPointerException e) {
			Log.e("log_tag", "Error in recieving response" + e.toString());
		}

		super.onResume();
	}

	/**
	 * Retrieves the current location from the location manager Determines if
	 * the user has approached the destination If the use is within 1 mile
	 * radius, the isVisited flag is set to true Updates the current position on
	 * the mapview
	 */
	@Override
	public void onLocationChanged(Location location) {
		GeoPoint currentLocation;

		currentLocation = new GeoPoint((int) (location.getLatitude() * 1E6),
				(int) (location.getLongitude() * 1E6));

		if (PlacesDirectionHelper.getDistanceInMiles(currentLocation,
				destGeoPoint) <= NEAR_TO)
			list.get(position).setIsVisited(true);
		if (!destGeoPoint.toString().equals("0,0"))
			drawUserPosition(currentLocation);

	}

	/**
	 * Places an overlay denoting the users current location on the route The
	 * route already covered by the user is drawn in Green and the route to be
	 * covered is drawn in blue After the path is drawn overlays are placed for
	 * - start location, current location and destination location
	 * 
	 * @param currentLocation
	 *            - GeoPoint for current location
	 */
	private void drawUserPosition(GeoPoint currentLocation) {

		MapDrawPathHelper.drawPath(srcGeoPoint, currentLocation, Color.GREEN,
				mapView);
		MapDrawPathHelper.drawPath(currentLocation, destGeoPoint, Color.BLUE,
				mapView);
		OverlayItem currentLocationOverlay = new OverlayItem(currentLocation,
				"Current Location", "Current Location");
		// mapOverlays.clear();
		if (locationOverlays.size() > 1) {
			// remove the old user position if there is one
			locationOverlays.removeOverlay(1);
		}
		// add new user position
		locationOverlays.addOverlay(currentLocationOverlay, this.getResources()
				.getDrawable(R.drawable.cur_arrow));
		mapOverlays.add(locationOverlays);
		mapView.getController().animateTo(currentLocation);

		mapView.getController().setZoom(15);

	}

	/**
	 * The On back pressed event is handled explicitly If the isVisited flag is
	 * true for any location an intent is sent to the overview activity so that
	 * it updates the list indicating the user has already visited the place.
	 */
	@Override
	public void onBackPressed() {
		Intent intent = new Intent(this, AdvancedOptionOverviewActivity.class);

		// Since we are using an emulator and wanted to run our app in normal
		// mode rather than debug mode
		// we will not be getting location updates (KLM file can only be used in
		// debug)
		// So we are assuming that a place is visited if route is viewed for
		// that place
		// However, if a KML is used then this option has to be uncommented so
		// that a place
		// is visited only if it is < 0.1 mile to the current location

		// intent.putExtra("pos",
		// position).putExtra("visit",list.get(position).getIsVisited());

		intent.putExtra("pos", position).putExtra("visit", true);
		setResult(RESULT_OK, intent);
		super.onBackPressed();
		finish();
	}

	@Override
	public void onProviderDisabled(String provider) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onProviderEnabled(String provider) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		// TODO Auto-generated method stub

	}

}
